c008b04965691b3115b458740e8af806e2c48414,Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java,ComputerPlayer,choose,#Outcome#Target#UUID#Game#Map#,211

Before Change


        }
        UUID opponentId = game.getOpponents(abilityControllerId).iterator().next();
        if (target instanceof TargetPlayer) {
            if (outcome.isGood()) {
                if (target.canTarget(abilityControllerId, game)) {
                    target.add(abilityControllerId, game);
                    return true;
                }
                if (target.isRequired(sourceId, game)) {
                    if (target.canTarget(opponentId, game)) {
                        target.add(opponentId, game);
                        return true;
                    }
                }
            } else {
                if (target.canTarget(opponentId, game)) {
                    target.add(opponentId, game);
                    return true;
                }
                if (target.isRequired(sourceId, game)) {
                    if (target.canTarget(abilityControllerId, game)) {
                        target.add(abilityControllerId, game);
                        return true;
                    }
                }
            }
            return false;
        }
        if (target instanceof TargetDiscard) {
            findPlayables(game);
            if (unplayable.size() > 0) {
                for (int i = unplayable.size() - 1; i >= 0; i--) {
                    if (target.canTarget(unplayable.values().toArray(new Card[0])[i].getId(), game)) {
                        target.add(unplayable.values().toArray(new Card[0])[i].getId(), game);
                        if (target.isChosen()) {
                            return true;
                        }
                    }
                }
            }
            if (hand.size() > 0) {
                for (int i = 0; i < hand.size(); i++) {
                    if (target.canTarget(hand.toArray(new UUID[0])[i], game)) {
                        target.add(hand.toArray(new UUID[0])[i], game);
                        if (target.isChosen()) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        if (target instanceof TargetControlledPermanent) {
            List<Permanent> targets;
            targets = threats(abilityControllerId, sourceId, ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
            if (!outcome.isGood()) {
                Collections.reverse(targets);
            }
            for (Permanent permanent : targets) {
                if (((TargetControlledPermanent) target).canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
                    target.add(permanent.getId(), game);
                    return true;
                }
            }
            return false;
        }
        if (target instanceof TargetPermanent) {
            List<Permanent> targets;
            if (outcome.isCanTargetAll()) {
                targets = threats(null, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
            } else {
                if (outcome.isGood()) {
                    targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                } else {
                    targets = threats(opponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                }
                if (targets.isEmpty() && target.isRequired()) {
                    if (!outcome.isGood()) {
                        targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                    } else {
                        targets = threats(opponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                    }
                }
            }
            for (Permanent permanent : targets) {
                if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
                    // stop to add targets if not needed and outcome is no advantage for AI player
                    if (target.getNumberOfTargets() == target.getTargets().size()) {
                        if (outcome.isGood() && hasOpponent(permanent.getControllerId(), game)) {
                            return true;
                        }
                        if (!outcome.isGood() && !hasOpponent(permanent.getControllerId(), game)) {
                            return true;
                        }
                    }
                    // add the target
                    target.add(permanent.getId(), game);
                    if (target.doneChosing()) {
                        return true;
                    }
                }
            }
            return target.isChosen();
        }

        if (target instanceof TargetCardInHand
                || (target.getZone().equals(Zone.HAND) && (target instanceof TargetCard))) {
            List<Card> cards = new ArrayList<>();
            for (UUID cardId : target.possibleTargets(sourceId, this.getId(), game)) {
                Card card = game.getCard(cardId);
                if (card != null) {
                    cards.add(card);
                }
            }
            while ((outcome.isGood() ? target.getTargets().size() < target.getMaxNumberOfTargets() : !target.isChosen())
                    && !cards.isEmpty()) {
                Card pick = pickTarget(cards, outcome, target, null, game);
                if (pick != null) {
                    target.addTarget(pick.getId(), null, game);
                    cards.remove(pick);
                }
            }
            return target.isChosen();
        }
        if (target instanceof TargetCreatureOrPlayer) {
            List<Permanent> targets;
            TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
            if (outcome.isGood()) {
                targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
            } else {
                targets = threats(opponentId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
            }
            for (Permanent permanent : targets) {
                List<UUID> alreadyTargetted = target.getTargets();
                if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
                    if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) {
                        target.add(permanent.getId(), game);
                        return true;
                    }
                }
            }
            if (outcome.isGood()) {
                if (target.canTarget(abilityControllerId, null, game)) {
                    target.add(abilityControllerId, game);
                    return true;
                }
            } else {
                if (target.canTarget(opponentId, null, game)) {
                    target.add(opponentId, game);
                    return true;
                }

After Change


    }

    @Override
    public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
        if (log.isDebugEnabled()) {
            log.debug("chooseTarget: " + outcome.toString() + ":" + target.toString());
        }
        // sometimes a target selection can be made from a player that does not control the ability
        UUID abilityControllerId = playerId;
        if (target.getTargetController() != null && target.getAbilityController() != null) {
            abilityControllerId = target.getAbilityController();
        }
        UUID randomOpponentId = getRandomOpponent(abilityControllerId, game);
        if (target instanceof TargetPlayer) {
            return setTargetPlayer(outcome, target, null, sourceId, abilityControllerId, randomOpponentId, game);
        }

        if (target instanceof TargetDiscard) {
            findPlayables(game);
            if (unplayable.size() > 0) {
                for (int i = unplayable.size() - 1; i >= 0; i--) {
                    if (target.canTarget(unplayable.values().toArray(new Card[0])[i].getId(), game)) {
                        target.add(unplayable.values().toArray(new Card[0])[i].getId(), game);
                        if (target.isChosen()) {
                            return true;
                        }
                    }
                }
            }
            if (hand.size() > 0) {
                for (int i = 0; i < hand.size(); i++) {
                    if (target.canTarget(hand.toArray(new UUID[0])[i], game)) {
                        target.add(hand.toArray(new UUID[0])[i], game);
                        if (target.isChosen()) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        if (target instanceof TargetControlledPermanent) {
            List<Permanent> targets;
            targets = threats(abilityControllerId, sourceId, ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
            if (!outcome.isGood()) {
                Collections.reverse(targets);
            }
            for (Permanent permanent : targets) {
                if (((TargetControlledPermanent) target).canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
                    target.add(permanent.getId(), game);
                    return true;
                }
            }
            return false;
        }
        if (target instanceof TargetPermanent) {
            List<Permanent> targets;
            if (outcome.isCanTargetAll()) {
                targets = threats(null, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
            } else {
                if (outcome.isGood()) {
                    targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                } else {
                    targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                }
                if (targets.isEmpty() && target.isRequired()) {
                    if (!outcome.isGood()) {
                        targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                    } else {
                        targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
                    }
                }
            }
            for (Permanent permanent : targets) {
                if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
                    // stop to add targets if not needed and outcome is no advantage for AI player
                    if (target.getNumberOfTargets() == target.getTargets().size()) {
                        if (outcome.isGood() && hasOpponent(permanent.getControllerId(), game)) {
                            return true;
                        }
                        if (!outcome.isGood() && !hasOpponent(permanent.getControllerId(), game)) {
                            return true;
                        }
                    }
                    // add the target
                    target.add(permanent.getId(), game);
                    if (target.doneChosing()) {
                        return true;
                    }
                }
            }
            return target.isChosen();
        }

        if (target instanceof TargetCardInHand
                || (target.getZone().equals(Zone.HAND) && (target instanceof TargetCard))) {
            List<Card> cards = new ArrayList<>();
            for (UUID cardId : target.possibleTargets(sourceId, this.getId(), game)) {
                Card card = game.getCard(cardId);
                if (card != null) {
                    cards.add(card);
                }
            }
            while ((outcome.isGood() ? target.getTargets().size() < target.getMaxNumberOfTargets() : !target.isChosen())
                    && !cards.isEmpty()) {
                Card pick = pickTarget(cards, outcome, target, null, game);
                if (pick != null) {
                    target.addTarget(pick.getId(), null, game);
                    cards.remove(pick);
                }
            }
            return target.isChosen();
        }
        if (target instanceof TargetCreatureOrPlayer) {
            List<Permanent> targets;
            TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
            if (outcome.isGood()) {
                targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
            } else {
                targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
            }
            for (Permanent permanent : targets) {
                List<UUID> alreadyTargetted = target.getTargets();
                if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
                    if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) {
                        target.add(permanent.getId(), game);
                        return true;
                    }
                }
            }
            if (outcome.isGood()) {
                if (target.canTarget(abilityControllerId, null, game)) {
                    target.add(abilityControllerId, game);
                    return true;
                }
            } else {
                if (target.canTarget(randomOpponentId, null, game)) {
                    target.add(randomOpponentId, game);
                    return true;
                }
            }
            if (!target.isRequired(sourceId, game)) {
                return false;
            }
        }

        if (target instanceof TargetPermanentOrPlayer) {
            List<Permanent> targets;
            TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target);
            List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
            List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
            if (outcome.isGood()) {
                targets = ownedTargets;
            } else {
                targets = opponentTargets;
            }
            for (Permanent permanent : targets) {
                List<UUID> alreadyTargetted = target.getTargets();
                if (t.canTarget(permanent.getId(), game)) {
                    if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) {
                        target.add(permanent.getId(), game);
                        return true;
                    }
                }
            }
            if (outcome.isGood()) {
                if (target.canTarget(abilityControllerId, null, game)) {
                    target.add(abilityControllerId, game);
                    return true;
                }
            } else {
                if (target.canTarget(randomOpponentId, null, game)) {
                    target.add(randomOpponentId, game);
                    return true;
                }
            }
            if (!target.isRequired(sourceId, game) || target.getNumberOfTargets() == 0) {
                return false;
            }
            if (target.canTarget(randomOpponentId, null, game)) {
                target.add(randomOpponentId, game);
                return true;
            }